import { Canvas, PPM } from './Canvas';
import { PortRadius, StudFigure } from './StudFigure';
import { WireFigure } from './WireFigure';
import { PartBase } from '../model/parts/PartBase';
import { Stud } from '../model/Stud';

export class PortDragHandle {

    public dragging:boolean = false
    public handle: raphaeljs.Element
    private line: raphaeljs.Element

    private draggingPort? : raphaeljs.Element
    public dropPort: any

    private portX : number = 0
    private portY : number = 0

    constructor(public canvas: Canvas){
        this.handle = canvas.paper.circle(100, 100, PortRadius*PPM)
                                .attr({fill: "#fff"})
                                .hide()
        $((this.handle as any)[0])
            .css("pointer-events", "none")
        this.line = canvas.paper
                            .path("M100,100L200,200")
                            .attr({stroke: "#2d8cf0", "stroke-dasharray":"--."})
                            .hide()
    }

    public setupPort(figure: StudFigure) {

        figure.port?.drag(
            // moving
            (dx:number, dy:number, x:number, y:number, e)=>{

                dx/= this.canvas.paper.viewbox.scale
                dy/= this.canvas.paper.viewbox.scale
                let cx = this.portX+dx
                let cy = this.portY+dy

                this.line.attr("path", `M${this.portX},${this.portY}L${cx},${cy}`)

                this.handle.attr({cx, cy})   

                // 实际发生拖拽，取消 stud 的 select 事件触发
                figure.selector.dragging(dx, dx)

                if( e ) {
                    if(e.cancelable)
                        e.preventDefault()
                    e.cancelBubble = true
                }
            }
            // start
            , (x:number, y:number, e)=>{
                this.draggingPort = figure.port as raphaeljs.Element

                ;({x: this.portX, y: this.portY} = figure.portPosition())

                this.line.toFront()
                        .attr("path", "M${this.portX},${this.portY}")
                        .show()

                this.handle
                        .attr({cx: this.portX, cy: this.portY})
                        .toFront()
                        .show()

                this.dragging = true
                
                if( e ) {
                    if(e.cancelable)
                        e.preventDefault()
                    e.cancelBubble = true
                }
            }
            // end
            , (event: any) => {
                // if(this.dropPort && this.dropPort!=figure.port.node) {
                //     this.canvas.emit("wire.new", figure, this.dropPort.studFigure)
                // }
                
                this.handle.hide()
                this.line.hide()
                this.dragging = false
                this.dropPort = null

                let range = 3.5*PPM
                let dx, dy

                // touch
                if(event.changedTouches) {
                    if(event.changedTouches.length<1)
                        return
                    var {x,y} = this.canvas.coords(event.changedTouches[0].clientX, event.changedTouches[0].clientY)
                }
                // mouse
                else {
                    var {x,y} = this.canvas.coords(event.offsetX, event.offsetY)
                }

                this.canvas.model?.eachPart((part:PartBase)=>{
                    let hit = part.eachStud((stud:Stud)=>{
                        if(stud.figure==figure)
                            return
                        if(stud.figure) {
                            if( stud.figure.hittest(x, y, range) ){
                                this.canvas.model?.createWire(figure.target, stud.figure.target)
                                return true
                            }
                        }
                    })
                    if( hit ) {
                        return true
                    }
                })
            }
        )

        $((figure.port as any)[0]).mouseover((e: MouseEvent)=>{
            if(!this.dragging)
                return
            this.dropPort = e.target
        })
        $((figure.port as any)[0]).mouseout(()=>{
            if(!this.dragging)
                return
            this.dropPort = null
        })
    }
}